//
//  ViewController.swift
//  Book
//
//  Created by iMac on 2018/9/27.
//  Copyright © 2018年 iMac. All rights reserved.
//

import Cocoa
import WebKit


class ViewController: NSViewController {
    
    //MARK: - property -
    @IBOutlet weak var textfield: NSTextField!
    @IBOutlet weak var button: NSButton!
    @IBOutlet weak var webview: WKWebView!
    @IBOutlet weak var favoritesMenu: NSPopUpButton!
    @IBOutlet weak var addFavoritesBtn: NSButton!
    @IBOutlet weak var textviewContainer: NSScrollView!
    @IBOutlet var textview: NSTextView!
    
    /// 当前的链接
    var curUrlStr = ""
    
    /// 支持快速翻页的网站列表
    /*
     "https://m.biquyun.com":
     """
     document.getElementsByClassName("content_top")[0].children[0].children[3].children[0].click()
     """,
     
     笔趣云网站可能挂了
     */
    
    let supportWebList = ["https://m.booktxt.net":
        """
        document.getElementById("pb_next").click()
        """,
                          "https://m.biqudu.net":
        """
        document.getElementById("pt_next").click()
        """,
                          "https://m.80txt.com":
        """
        document.getElementById("pt_next").click()
        """,
                          ]
    
    lazy var contentView = {
        return NSView()
    }()
    
    var readModeOn = false
    
    var requestLimit = true
    
    var lastMaxY = 0 {
        didSet {
            if lastMaxY - oldValue > 500 {
                requestLimit = true
            }
        }
    }
    
    
    //MARK: - life cycle -
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        textfield.stringValue = UserDefaults.standard.string(forKey: "lastUrlStr") ?? ""
        
        configWebview()
        configContentview()
        configFavoritesMenu()
        
    }
    
    override func viewDidAppear() {
        super.viewDidAppear()
        //必须在willAppear之后，window才有值
        self.view.window?.delegate = self
    }
    
    override func viewDidDisappear() {
        super.viewDidDisappear()
        
        print("done - \(curUrlStr)")
        UserDefaults.standard.set(curUrlStr, forKey: "lastUrlStr")
        UserDefaults.standard.synchronize()
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }
    
    //MARK: - UI Response -

    @IBAction func goToWeb(_ sender: NSButton) {
        print("text -- \(textfield.stringValue)")
        var urlstr = textfield.stringValue
        guard urlstr != "" else {
            return
        }
        
        if !urlstr.hasPrefix("http") {
            urlstr = "http://".appending(urlstr)
        }
        if let url = URL.init(string: urlstr) {
            let request = URLRequest.init(url: url)
            webview.load(request)
        }
        
    }
    
//    @IBAction func biquge_Go(_ sender: NSButton) {
//        let urlstr = "https://m.biquyun.com"
//        if let url = URL(string: urlstr) {
//            let request = URLRequest(url: url)
//            webview.load(request)
//        }
//    }
    
    @IBAction func booktxt_Go(_ sender: NSButton) {
        let urlstr = "https://m.booktxt.net"
        if let url = URL(string: urlstr) {
            let request = URLRequest(url: url)
            webview.load(request)
        }
    }
    
    @IBAction func biqudu_Go(_ sender: NSButton) {
        let urlstr = "https://m.biqudu.net"
        if let url = URL(string: urlstr) {
            let request = URLRequest(url: url)
            webview.load(request)
        }
    }
    
    @IBAction func txt80_Go(_ sender: NSButton) {
        let urlstr = "https://m.80txt.com"
        if let url = URL(string: urlstr) {
            let request = URLRequest(url: url)
            webview.load(request)
        }
    }
    
    @IBAction func addFavoritesAction(_ sender: NSButton) {
        var list = UserDefaults.standard.array(forKey: "FAVORITES_LIST") as? [String] ?? [String]()
        guard curUrlStr.count > 0 && !list.contains(curUrlStr) else {
            return
        }
        
        list.append(curUrlStr)
        UserDefaults.standard.set(list, forKey: "FAVORITES_LIST")
        UserDefaults.standard.synchronize()
        configFavoritesMenu()
    }
    
    @IBAction func readModeAction(_ sender: NSButton) {
        readModeOn = !readModeOn
        if readModeOn {
            //打开
            textviewContainer.isHidden = false
            webview.isHidden = true
            configTextview()
        } else {
            textviewContainer.isHidden = true
            webview.isHidden = false
            textview.string = ""
        }
    }
    
    //MARK: - Private func -
    /// 配置过滤规则
    private func configWebview() {

        let blockStr = """
            [
                {
                    "trigger":{
                        "url-filter":".*",
                        "if-domain":[
                            %@
                        ],
                        "load-type": ["third-party"]
                    },
                    "action":{
                        "type": "block"
                    }
                }
            ]
            """
        
        let domainString = supportWebList.keys.map({"\""+($0.split(separator: "/").last ?? "")+"\""}) .joined(separator: ",")
        
        let jsonString = String(format: blockStr, domainString)
        
        WKContentRuleListStore.default()?.compileContentRuleList(forIdentifier: "adv_block", encodedContentRuleList: jsonString, completionHandler: { (list, error) in
            
            guard let contentRuleList = list else {
                print(error as Any)
                return
            }
            let configuration = self.webview.configuration
            configuration.userContentController.add(contentRuleList)
            
        })
        
    }
    
    private func configTextview() {
        
        let getHtml_js = "document.documentElement.innerHTML"
        webview.evaluateJavaScript(getHtml_js) { [weak self](html, error) in
//            print(html)
            let text = self?.dealHtmlStr(host: self?.curUrlStr ?? "", html: (html as? String) ?? "")
            self?.textview.string = (self?.textview.string ?? "") + text!
        }
        
    }
    
    private func configContentview() {
        contentView.frame = NSRect(x: 0, y: 0, width: self.view.frame.width*2-30, height: 15)
        for view in contentView.subviews {
            view.removeFromSuperview()
        }
        let icon = NSView(frame: NSRect.init(x: self.view.frame.width-30, y: 0, width: 30, height: 15))
        icon.wantsLayer = true
        icon.layer?.backgroundColor = CGColor(red: 1, green: 1, blue: 0, alpha: 1)
        contentView.addSubview(icon)
        
        //配置阅读模式
        textview.font = NSFont(name: "STLibianSC-Regular", size: 20)
        textview.isEditable = false
        
        //监听textviewContainer滑动
        NotificationCenter.default.addObserver(self, selector: #selector(getNextView(noti:)), name: NSView.boundsDidChangeNotification, object: textviewContainer.contentView)
    }
    
    func configFavoritesMenu() {
        favoritesMenu.removeAllItems()
        if let list = UserDefaults.standard.array(forKey: "FAVORITES_LIST") as? [String] {
            for url in list {
                if url == "" {
                    continue
                }
                let item = NSMenuItem(title: url, action: #selector(goToFavoritesWeb), keyEquivalent: "")
                item.submenu = NSMenu(title: url)
                item.submenu?.addItem(NSMenuItem(title: "-", action: #selector(removeFavoritesWeb(sender:)), keyEquivalent: ""))
                favoritesMenu.menu?.addItem(item)
            }
        }
        favoritesMenu.title = "收藏"
    }
    
    private func dealHtmlStr(host: String, html: String) -> String {
        if host.hasPrefix("https://m.booktxt.net") {
            
            let regular = re.compile("<div\\sid=\"chaptercontent\"\\sclass=\"Readarea\\sReadAjax_content\"\\sstyle=\"font-size:\\s20px;\">(.*?)</div>", flags: .dotMatchesLineSeparators)
            if let matches = regular.search(html) {
                var text = matches.group(1)!
                text = (text as NSString).replacingOccurrences(of: "<br>", with: "\n")
                text = (text as NSString).replacingOccurrences(of: "&nbsp;", with: " ")
                let re_p = re.compile("<p.*?</p>", flags: .dotMatchesLineSeparators)
                text = re_p.sub("\n\n\n", text)
                text = (text as NSString).trimmingCharacters(in: .whitespacesAndNewlines)
                text = "\n\n    " + text + "\n\n====================="
                
                return text
            }
            
        } else if host.hasPrefix("https://m.biquyun.com") {
            let regular = re.compile("<div\\sid=\"novelcontent\"\\sclass=\"novelcontent\">(.*?)</div>", flags: .dotMatchesLineSeparators)
            if let matches = regular.search(html) {
                var text = matches.group(1)!
                text = (text as NSString).replacingOccurrences(of: "<br>", with: "\n")
                text = (text as NSString).replacingOccurrences(of: "&nbsp;", with: " ")
                let re_p = re.compile("<p>(.*?)</p>", flags: .dotMatchesLineSeparators)
                text = re_p.search(text)?.group(1) ?? ""
                text = (text as NSString).trimmingCharacters(in: .whitespacesAndNewlines)
                text = "\n\n    " + text + "\n\n====================="
                
                return text
            }
            
        } else if host.hasPrefix("https://m.biqudu.net") || host.hasPrefix("https://m.80txt.com") {
            let regular = re.compile("<div\\sid=\"nr1\">(.*?)</div>", flags: .dotMatchesLineSeparators)
            var text = regular.search(html)?.group(1) ?? ""
            text = (text as NSString).replacingOccurrences(of: "<br>", with: "\n")
            text = (text as NSString).replacingOccurrences(of: "&nbsp;", with: " ")
            text = (text as NSString).trimmingCharacters(in: .whitespacesAndNewlines)
            text = "\n\n    " + text + "\n\n====================="
            
            return text
        }
        
        return ""
    }

    private func requestNewview() {

        let js = supportWebList.keys.reduce("", {
            if curUrlStr.hasPrefix($1) {
                return (supportWebList[$1] ?? "") + $0
            }
            return "" + $0
        })

        webview.evaluateJavaScript(js, completionHandler: nil)
    }
    
    @objc private func goToFavoritesWeb () {
        if let urlstr = favoritesMenu.titleOfSelectedItem, let url = URL(string: urlstr) {
            let request = URLRequest(url: url)
            webview.load(request)
        }
        favoritesMenu.title = "收藏"
    }
    
    @objc private func removeFavoritesWeb (sender : NSMenuItem) {
        let url = sender.menu?.title
        if let list = UserDefaults.standard.array(forKey: "FAVORITES_LIST") as? [String] {
            let newlist = list.filter { $0 != url && $0 != "" }
            UserDefaults.standard.set(newlist, forKey: "FAVORITES_LIST")
            UserDefaults.standard.synchronize()
        }
        configFavoritesMenu()
    }
    
//MARK: - 通知 -
    //MARK: boundsDidChangeNotification
    @objc private func getNextView(noti: NSNotification) {
        /// self.contentView.documentVisibleRect 可见范围 相当于 UIScrollerView 的 contentSize
//        print("\(#function) -- \(textviewContainer.contentView.documentVisibleRect) -- \(textviewContainer.contentView.documentRect)")
        
        let yP = textviewContainer.contentView.documentVisibleRect.origin.y
        let maxY = textviewContainer.contentView.documentRect.size.height
        lastMaxY = Int(maxY)
        
        if yP > 100 && maxY - yP < 1600 && requestLimit {
            requestLimit = false
            requestNewview()
        }
    }
    
}

extension ViewController: NSWindowDelegate {
    //MARK: - NSWindowDelegate
    func windowDidResize(_ notification: Notification) {
        configContentview()
    }
}


extension ViewController: WKNavigationDelegate, WKUIDelegate {
    //MARK: - WKNavigationDelegate
    
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        print("\(#function)")
        print("\(String(describing: navigationAction.request.url?.absoluteString))")
        
        decisionHandler(.allow)
    }
    
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        print("error -- \(error)")
    }
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("\(#function)")
        
        if readModeOn {
            configTextview()
        }
    }
    
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        print("\(#function)")
        print("load url -- \(String(describing: webView.url))")
        
        curUrlStr = webView.url?.absoluteString ?? ""
    }
    
    //MARK: - WKUIDelegate
    func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
        print("\(#function)")
        if navigationAction.targetFrame == nil || !navigationAction.targetFrame!.isMainFrame {
            webView.load(navigationAction.request)
        }
        return nil
    }
}







/*
 
 //暂时不用的规则
 """
 {
 "trigger":{
 "url-filter":".*",
 "unless-domain": ["m.biquge.com.tw"]
 },
 "action":{
 "type": "block"
 }
 },
 {
 "trigger":{
 "url-filter":"https://"
 },
 "action":{
 "type": "block"
 }
 },
 {
 "trigger":{
 "url-filter":".*(?!biquge)"   //Error while parsing .*(?!biquge): Groups are not supported yet.
 },
 "action":{
 "type": "block"
 }
 },
 """
 
 
 """
 [{
 "trigger":{
 "url-filter":"^((?!biquge).)*$",
 "if-domain":[
 "m.biquge.com.tw"
 ]
 },
 "action":{
 "type": "block"
 }
 
 }]
 """
 
 */
